perm filename UPD.CNV[C,JRA]1 blob
sn#019578 filedate 1973-01-10 generic text, type T, neo UTF8
ON PATTERN DIRECTED INVOCATION
Methods can be invoked in association with adding items to,
fetching items from, and removing items from the data base. The
invocation depends on a match between the method's pattern and
the item, a match being an assignment of values to the pattern's
variables that will make it EQUAL to the item. Since when if-
needed methods are called, it is necessary to match two patterns
against each other, the matcher always returns a list of two
alists that specify assignments of as many variables on both
sides as possible. If there is no match, NIL is returned.
The matcher may be called by (MATCH varpat datapat); MATCH
is asymmetric in that it is biased toward assigning variables in
varpat to constants from the other side. A pattern is a non-
circular list structure with "variable parts" marked by the
prefixes "!>" and "!,". "!>var" must match a variable-free
section of datapat. (This restriction will always be met when
patterns are matched against items.) Matching "!>var" against
something causes var to be bound on the alist for variables in
varpat, with a value corresponding to what is matched. For
example, (MATCH '(FOO !>X) '(FOO BAR)) returns (((X BAR)) NIL).
(Here, "NIL" is the alist for variables in (FOO BAR).)
The matcher is multi-level (that is, variables can occur
below the top level of list structure), and dots are allowed in
patterns, as (DINO DESI . !>X). Hence, the pattern ((FREDS !>X)
. !>REST) matches
PAGE 2
((FREDS FATHER) WHISTLES)
((FREDS FATHER) WHISTLES DIXIE)
((FREDS GONE) HE SAID),
generating association lists
((X FATHER) (REST (WHISTLES)))
((X FATHER) (REST (WHISTLES DIXIE)))
((X GONE) (REST (HE SAID))),
respectively. (The second lists are always NIL in these cases.)
When FETCH calls the matcher, it uses the varpat alist to
make up an item possibility. Thus, if items (SPIRO SUCKS ROCKS)
and (SPIRO SUCKS DICK) are present in the current context, (FETCH
'(SPIRO SUCKS !>WHAT)) might return
(*POSSIBILITIES *IGNORE
(*ITEM ((SPIRO SUCKS ROCKS) (10 +)) ((WHAT ROCKS)))
(*ITEM ((SPIRO SUCKS DICK) (0 +)) ((WHAT DICK)))).
TRY-NEXT takes the association lists from item possibilities
and assigns the variables as they direct.
The other principal prefix is "!,", which refers to the
current binding of its variable in the match so far, or the
current Conniver binding, and matches its value. For example,
the pattern (GRANDFATHER !>X !,X) matches all items corresponding
to people who are their own grandfathers.
Another frill is the ability to specify a restricted match
If "!>" prefixes a non-atomic expression, its CDR is a list of
forms that must all evaluate (in Lisp) to non-NIL after
PAGE 3
assignment of its CAR. For example, !>(X (ATOM !,X)) matches
only atoms, and !>(CREATURE (FEATHERLESS !,CREATURE) (EQ (NUMBER-
OF-LEGS !,CREATURE) 2)) matches featherless bipeds. If it is
desired to bind and initialize a variable in its pattern's alist,
ne can write "!,(var initial-value)." For example, (FUNCT-OF
!>FORM !,(F (CAR !,FORM))) matches (FUNCT-OF (FACTORIAL 5)
FACTORIAL) but not (FUNCT-OF (PLUS 2 2) MINUS). Finally, if it
is desired to specify an item shape without naming or saving its
parts, the prefix characters "!>" can stand alone. Thus, (FETCH
'(FOO !>)) returns a possibilities list of items of the form (FOO
x), but applying TRY-NEXT to it sets no variables.
If-addeds and if-removeds work nicely with MATCH. To invoke
one, Conniver applies MATCH to its pattern and the item that
triggered it. If the result is non-NIL, the varpat alist is used
to start the variable bindings in the method's frame (which may
be augmented by "AUX" bindings).
An if-needed method is really an entirely different kind of
entity. First, its match occurs at FETCH-time, its alists being
saved in a *METHOD possibility until TRY-NEXT calls it. Second,
such a method is a kind of callable subroutine, which should be
capable of more than verifying or achieving conditions
represented by constant patterns. In particular, one would like
to be able to specify that a slot represents an output variable,
to be set by the method but not by the match. This is
accomplished by use of the prefix "!<"; "!<var" matches only
PAGE 4
expressions with variables (var being assigned to that
expression, but only so the user can see what is going to happen
on output).
Thus, when (NOTE (INSTANCE)) is called to create a value to
be added to the possibilities list, MATCH is called again in a
special (secret) way, this time with the FETCH-pattern as varpat,
which treats the method pattern as an essentially constant
structure whose variable slots are to be filled as indicated by
the values the variables have picked up in the method.
As an example, consider the method
IF-NEEDED FIND-SUPPORTERS
(ON !>X !<Y)
"AUX" ((P (FETCH '(SUPPORTS !>Y !,X))))
LOOP
(TRY-NEXT P '(ADIEU))
(AU-REVOIR (INSTANCE))
(GO 'LOOP) ).
This method will appear in a FETCH-possibilities-list generated
by, e.g., (FETCH '(ON BOX1 !>B)), but not one generated by, e.g.,
(FETCH '(ON !>A TABLE)), which is looking for "supportees" of an
object called TABLE. When FIND-SUPPORTERS is entered, X will
have the value BOX1, and Y the value !>B. At statement :LOOP, Y
is set to the next supporter of BOX1. One such supporter is
returned each time the method is entered or re-entered.
Notice that this method has a completely different purpose
from one with the pattern (ON !<X !>Y), which would find the
supportees" of a given object Y; or one with pattern (ON !>X
PAGE 5
!>Y), which verifies a support relation.
Occasionally, however, one wishes the decision of what to do
in cases differing in this way to be made after the method is
entered. In this case, one can use the prefix "!?" which is
ambiguous; its variable is assigned if and only if it matches a
variable-free expression. The complementary ambiguity on the
FETCH-side is handled by the prefix "!;" which means "!>" if its
variable is unbound in the current match alist and unassigned by
Conniver; or "!," if its variable is assigned or bound in the
match alist but unassigned. These characters are typically handy
in situations where a pattern is to be expanded according to its
definition, regardless of exactly what is variable in it. For
example, if men are always to be treated as featherless bipeds,
the following method does the conversion if one is looking for
men or attempting to verify that something is a man:
IF-NEEDED IS-MAN
(IS !?X MAN)
"AUX" ((P (FETCH '(IS !;X BIPED))))
LOOP
(TRY-NEXT P '(ADIEU))
(COND ((PRESENT '(FEATHERLESS !,X))
(AU-REVOIR (INSTANCE))) )
(GO 'LOOP) ).
t takes the place of the two methods that would be required
without "!?" and "!;", which would have "!<" and "!>", or "!>"
and "!," instead. (Micro-Planner users please note that the
micro-Planner prefix "$?" includes both ambiguities, and would
take the place of all prefixes used in IS-MAN.)
PAGE 6
Finally, some if-needed methods claim to be able to expand on
the syntactic forms of calling patterns rather than to be able to
generate items similar to those represented by those patterns.
The corresponding method-pattern variables are signaled by the
prefix "!'", which is analogous to the "'" of CEXPR bound
variable declarations. "!'var" binds var to an expression
without examining its internal structure in any way; its
variables are neither substituted or bound. For example, a
method for causing (FETCH '(AND *conjuncts*)) to set the
variables in the conjuncts correctly might look like:
IF-NEEDED AND-EXPANDER
(AND . !'CONJUNCTS)
(COND (CONJUNCTS
"AUX" ((P1 (FETCH (CAR CONJUNCTS)))
(P2 (FETCH !"(AND . @(CDR ,CONJUNCTS))))
COP2)
:LOOP1
(TRY-NEXT P1 '(ADIEU))
(CSETQ COP2 (COPY P2))
:LOOP2
(TRY-NEXT COP2 '(GO 'LOOP1))
(AU-REVOIR (INSTANCE))
(GO 'LOOP2))
((AU-REVOIR (INSTANCE))) )).
or example, if the items (GREEN BOX3), (GREEN BOX1), (GREEN
BOX4), (ON BOX1 BOX2), and (ON BOX4 BOX5) are in the data base,
repeatedly TRY-NEXTing (FETCH '(AND (GREEN !>X) (ON !,X !>Y)))
will set X to BOX1 and Y to BOX2, then X to BOX4 and Y to BOX5,
then quit. The method's value is always (*NOTE NIL), because it
never concerns itself with binding calling pattern variables. (A
more efficient implementation, by the way, is obviously
PAGE 7
possible.)
All the syntactic frills such as restrictions and bound
variable initialization are legal in method patterns. However,
it is generally meaningless to restrict a "!<"-marked variable.
If !<(X (ATOM !,X)) appears in a pattern, it is not clear what is
being restricted. It is certainly not possible by such a
restriction to prevent future assignments of X to anything
non-atomic. All restrictions will be run only at match time.
In the case of "!?", restrictions will be run only if the prefixed
variable is assigned in the match.